package br.com.massai.model.entity;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import br.com.massai.view.enums.Flow;
import br.com.massai.view.enums.TypePayroll;

@Entity
@Table(name = "SPREADSHEET") //uniqueConstraints = @UniqueConstraint(columnNames={"ACCRUAL_BASIS", "TYPE_PAYROLL", "DEPARTMENT_ID"})
@NamedQueries({
	@NamedQuery(name = "Spreadsheet.find", query = "SELECT s FROM Spreadsheet s"),
	@NamedQuery(name = "Spreadsheet.count", query = "SELECT COUNT(s) FROM Spreadsheet s"),
	@NamedQuery(name = "Spreadsheet.duplicate", query = "SELECT COUNT(s) FROM Spreadsheet s WHERE s.accrualBasis =:accrualBasis AND s.typePayroll =:typePayroll AND s.department =:department AND s.deleted <> true")
})
public class Spreadsheet extends GenericEntity {

	private static final long serialVersionUID = 6083690478411373564L;

	@Id
	@SequenceGenerator(name = "seqSpreadsheet", sequenceName = "seq_spreadsheet", allocationSize = 1)
	@GeneratedValue(generator = "seqSpreadsheet", strategy = GenerationType.SEQUENCE)
	private Long id;
	
	@Column(name = "CODE", nullable = false, columnDefinition = "INTEGER")
	private Integer code;

	@Column(name = "ACCRUAL_BASIS", nullable = false, length = 6, columnDefinition = "VARCHAR(6)")
	private String accrualBasis;

	@Enumerated(EnumType.STRING)
	@Column(name = "FLOW", nullable = false, columnDefinition = "VARCHAR(10)")
	private Flow flow;

	@Enumerated(EnumType.STRING)
	@Column(name = "TYPE_PAYROLL", length = 1, nullable = false, columnDefinition = "CHAR(1)")
	private TypePayroll typePayroll;

	@Column(name = "OBSERVATION", columnDefinition = "TEXT")
	private String observation;

	@Column(name = "OBSERVATION_ANALYSIS", columnDefinition = "TEXT")
	private String observationAnalysis;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "DATE_REGISTER", nullable = false)
	private Date dateRegister;

	@ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
	@Fetch(FetchMode.JOIN)
	@JoinColumn(name = "DEPARTMENT_ID", referencedColumnName = "ID")
	private Department department;
	
	@Column(name="DELETED", nullable = false, columnDefinition = "BOOLEAN DEFAULT false")
	private boolean deleted;

	@Transient
	private Collaborator collaboratorLogged;

	@Transient
	private boolean toAnalisys;
	
	//PROPRIEDADES DA IMPORTACAO - FORTES
	@Column(name="SEQUENCIAL", length = 8, columnDefinition = "VARCHAR(8)")
	private String sequencial;
	
	@Column(name = "TOTAL_SALARIO", precision = 15, scale = 2, columnDefinition = "NUMERIC(15,2)")
	private BigDecimal totalSalario; 

	public Spreadsheet() {
		this.toAnalisys = false;
		this.totalSalario = BigDecimal.ZERO;
	}

	@Override
	public Map<String, Object> getParameters() {
		super.clearParameters();

		if(this.accrualBasis != null && !this.accrualBasis.trim().isEmpty()){
			super.addClauseWhere("s.accrualBasis =:accrualBasis", ConditionType.AND);
			super.addParameters("accrualBasis", this.accrualBasis);
		}
		
		if(this.department != null && this.department.getId() != null){
			super.addClauseWhere("s.department =:depart", ConditionType.AND);
			super.addParameters("depart", this.department);
		}

		if(this.typePayroll != null){
			super.addClauseWhere("s.typePayroll =:typePayroll", ConditionType.AND);
			super.addParameters("typePayroll", this.typePayroll);
		}

		//FILTRO PARA PLANILHAS DE USUARIOS LOGADOS
		if(this.collaboratorLogged != null && this.collaboratorLogged.getId() != null){
			super.addClauseWhere("s IN (SELECT s FROM Spreadsheet s JOIN s.department d JOIN d.collaborators u WHERE u = :collaborator)", ConditionType.AND);
			super.addParameters("collaborator", this.collaboratorLogged);
		}

		if(this.flow != null){
			super.addClauseWhere("s.flow =:flow", ConditionType.AND);
			super.addParameters("flow", this.flow);

		} else {
			if(this.toAnalisys){
				super.addClauseWhere("s.flow <> :flowOpen", ConditionType.AND);
				super.addClauseWhere("s.flow <> :flowRevision", ConditionType.AND);
				super.addParameters("flowOpen", Flow.OPEN);
				super.addParameters("flowRevision", Flow.REVISION);
			} else {
				super.addClauseWhere("s.flow <> :flow", ConditionType.AND);
				super.addParameters("flow", Flow.PENDANT);
			}
		}

		//FILTRO POR PLANILHAS AINDA NAO DELETADAS
		super.addClauseWhere("s.deleted = :deletedS", ConditionType.AND);
		super.addParameters("deletedS", false);
		
		//FILTRO POR DEPARTAMENTOS AINDA NAO DELETADOS
		super.addClauseWhere("s.department.deleted = :deleted", ConditionType.AND);
		super.addParameters("deleted", false);

		return super.getParameters();
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj == null) return false;
		if(obj instanceof Spreadsheet)
			if(((Spreadsheet)obj).getId().equals(this.id)) return true;

		return false;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getAccrualBasis() {
		return accrualBasis;
	}

	public void setAccrualBasis(String accrualBasis) {
		this.accrualBasis = accrualBasis;
	}

	public Flow getFlow() {
		return flow;
	}

	public void setFlow(Flow flow) {
		this.flow = flow;
	}

	public TypePayroll getTypePayroll() {
		return typePayroll;
	}

	public void setTypePayroll(TypePayroll typePayroll) {
		this.typePayroll = typePayroll;
	}

	public String getObservation() {
		return observation;
	}

	public void setObservation(String observation) {
		this.observation = observation;
	}

	public String getObservationAnalysis() {
		return observationAnalysis;
	}

	public void setObservationAnalysis(String observationAnalysis) {
		this.observationAnalysis = observationAnalysis;
	}

	public Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}

	public Integer getCode() {
		return code;
	}

	public void setCode(Integer code) {
		this.code = code;
	}

	public boolean isToAnalisys() {
		return toAnalisys;
	}

	public void setToAnalisys(boolean toAnalisys) {
		this.toAnalisys = toAnalisys;
	}

	public Date getDateRegister() {
		return dateRegister;
	}

	public void setDateRegister(Date dateRegister) {
		this.dateRegister = dateRegister;
	}

	public Collaborator getCollaboratorLogged() {
		return collaboratorLogged;
	}

	public void setCollaboratorLogged(Collaborator collaboratorLogged) {
		this.collaboratorLogged = collaboratorLogged;
	}

	public boolean isDeleted() {
		return deleted;
	}

	public void setDeleted(boolean deleted) {
		this.deleted = deleted;
	}

	public String getSequencial() {
		return sequencial;
	}

	public void setSequencial(String sequencial) {
		this.sequencial = sequencial;
	}

	public BigDecimal getTotalSalario() {
		return totalSalario;
	}

	public void setTotalSalario(BigDecimal totalSalario) {
		this.totalSalario = totalSalario;
	}
}
